#include "EchoEngine.h"
#include <cstddef>
#include <cstdint>
#include "DateTime.h"
#include "Logger.h"

using namespace std::placeholders;
using namespace xncc::user;
using namespace xncc::types;
EchoEngine::EchoEngine(int id) : EventEngine(id)
{
}

void EchoEngine::init()
{
    auto testFunc = std::bind(&EchoEngine::handleTestMsg, this, _1, _2, _3, _4);
    registerUserFunc(1000, testFunc);
}

void EchoEngine::handleConnected(connection_id_t msg, thread_id_t tid)
{
    LOG_INFO(CONSOLE_LOG) << "EchoEngine " << id() << " receive conn msg  peer addr = " << getPeerAddr(msg)
                          << " connid:" << msg;
    xncc::types::timer_id_t id =
        setTimerFunc(DateTime::timeMicro() + 10 * 1000000, 0, std::bind(&EchoEngine::closeClient, this, tid, msg));
    if (id == INVALID_TIMER_ID) {
        LOG_ERROR(CONSOLE_LOG) << "create timer failed";
    }
    conn_ids_[msg] = false;
}

void EchoEngine::handleTestMsg(const char* buf, uint32_t len, thread_id_t tid, connection_id_t connId)
{
    std::string rsp(buf, static_cast<std::size_t>(len));
    LOG_INFO(CONSOLE_LOG) << "EchoEngine " << id() << " connid:" << connId << " receive client msg = " << rsp;
    sendData(rsp.c_str(), static_cast<uint32_t>(rsp.size()), 1000, tid, connId);
    conn_ids_[connId] = true;
}

void EchoEngine::handleDisconnected(connection_id_t msg, thread_id_t tid, const std::string& disconnectedReason)
{
    LOG_INFO(CONSOLE_LOG) << "EchoEngine " << id() << "  receive dis conn msg  peer addr = " << getPeerAddr(msg)
                          << " connid:" << msg << " reason:" << disconnectedReason;
    conn_ids_.erase(msg);
}

void EchoEngine::closeClient(xncc::types::thread_id_t tid, xncc::types::connection_id_t connId)
{
    if (conn_ids_.find(connId) == conn_ids_.end()) {  // 已经断开
        LOG_INFO(CONSOLE_LOG) << "EchoEngine " << id() << " client:" << connId << " has disconnected";
    }
    else {
        if (conn_ids_[connId] == false) {  // 没发送消息
            LOG_INFO(CONSOLE_LOG) << "EchoEngine " << id() << " client:" << connId << " addr:" << getPeerAddr(connId)
                                  << " has no send any message, close it";
            kickConnection(connId, tid);
        }
    }
}